//
//  RSNumberTest.m
//  RSMath
//
//  Copyright (c) 2007-2009 Raphael Sobik. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are met:
//  1. Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//  3. The name of the author may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY Raphael Sobik "AS IS" AND ANY EXPRESS
//  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
//  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
//  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
//  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
//  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#import "RSNumberTest.h"


@implementation RSNumberTest

- (void)setUp
{
	zero = [[RSNumber alloc] initWithInteger:0];
	one  = [[RSNumber alloc] initWithInteger:1];
	pos  = [[RSNumber alloc] initWithInteger:3452];
	neg  = [[RSNumber alloc] initWithInteger:-1234];
	prime = [[RSNumber alloc] initWithInteger:11];
    unsignedInteger = [[RSNumber alloc] initWithUnsignedInteger:234];
}

- (void)tearDown
{
	[zero release];
	[one release];
	[pos release];
	[neg release];
	[prime release];
    [unsignedInteger release];
}

- (void)testObjectCreationAndStringMethod
{
	RSNumber *num = [RSNumber numberWithString:@"1"];
	
	STAssertNotNil([RSNumber number], @"Number could not be instatiated");
	STAssertTrue([[zero string] isEqualToString:@"0"], nil);
	STAssertFalse([[one string] isEqualToString:@"12"], nil);
	STAssertTrue([[num string] isEqualToString:[one string]], nil);
    STAssertTrue([[unsignedInteger string] isEqualToString:@"234"], nil);
}

- (void)testComparsionMethods
{
	STAssertTrue([zero isZero], nil);
	STAssertFalse([one isZero], nil);
	
	STAssertTrue([one isOne], nil);
	STAssertFalse([zero isOne], nil);
	
	STAssertTrue([neg isNegative], nil);
	STAssertFalse([pos isNegative], nil);

	STAssertTrue([zero isLargerThan:neg], nil);
	STAssertFalse([neg isLargerThan:pos], nil);
	
	STAssertFalse([zero isEqualToNumber:[RSNumber numberWithInteger:6]], nil);
	STAssertTrue([zero isEqualToNumber:[RSNumber numberWithInteger:0]], nil);
	STAssertFalse([zero isEqualTo:[RSNumber numberWithInteger:6]], nil);
	STAssertTrue([zero isEqualTo:[RSNumber numberWithInteger:0]], nil);

	STAssertTrue([neg isSmallerThan:zero], nil);
	STAssertFalse([pos isSmallerThan:neg], nil);
}

- (void)testTheoreticFunctions
{
	STAssertTrue([prime isPrime], nil);
	STAssertFalse([neg isPrime], nil);
	STAssertFalse([pos isPrime], nil);
}

- (void)testPrimeGeneration
{
    NSArray *primes = [RSMath primesUpto:[RSNumber numberWithInteger:20]];
    RSNumber *eight = [RSNumber numberWithInteger:8];
    RSNumber *count = [RSNumber numberWithUnsignedInteger:[primes count]];
    STAssertTrue([count isEqualTo:eight], @"Count of primes is %@, should be 8", [count string]);
}

- (void)testFacorisation
{
    //IMPLEMENTATION OF FACTORIZATION TEST
    RSNumber *twenty = [RSNumber numberWithInteger:20];
    NSArray *factors = [twenty factorization];
    RSNumber *num = [RSNumber numberWithUnsignedInteger:[factors count]];
    RSNumber *three = [RSNumber numberWithInteger:3];
    STAssertTrue([num isEqualTo:three], @"factors count is: %@", [num string]);
}

- (void)testArtihmeticOperations
{
	//-(RSNumber *) mod:(RSNumber *)mod;
	RSNumber *number = [RSNumber numberWithInteger:102];
	RSNumber *result = [number mod:[RSNumber numberWithInteger:100]];
	STAssertTrue([result isEqualToNumber:[RSNumber numberWithInteger:2]], nil);

	
	//-(RSNumber *) inverseMod:(RSNumber *)mod;
	number = [RSNumber numberWithInteger:10];
	RSNumber *inverse = [number inverseMod:[RSNumber numberWithInteger:13]];
	STAssertTrue([inverse isEqualToNumber:[RSNumber numberWithInteger:4]], nil);
	
	
	//-(RSNumber *) add:(RSNumber *)otherNumber;
	RSNumber *sum = [number add:inverse];
	STAssertTrue([sum isEqualToNumber:[RSNumber numberWithInteger:14]], nil);
	
	//-(RSNumber *) add:(RSNumber *)otherNumber mod:(RSNumber *)mod;
	sum = [number add:inverse mod:[RSNumber numberWithInteger:12]];
	STAssertTrue([sum isEqualToNumber:[RSNumber numberWithInteger:2]], nil);
	
	
	//-(RSNumber *) subtract:(RSNumber *) otherNumber;
	RSNumber *sub = [number subtract:[RSNumber numberWithInteger:5]];
	STAssertTrue([sub isEqualToNumber:sub], nil);
	
	//-(RSNumber *) subtract:(RSNumber *) otherNumber mod:(RSNumber *)mod;
	sub = [number subtract:[RSNumber numberWithInteger:5] mod:[RSNumber numberWithInteger:4]];
	STAssertTrue([sub isEqualToNumber:one], nil);
	
	//-(RSNumber *) multiplyWith:(RSNumber *) otherNumber;
	RSNumber *mul = [number multiplyWith:[RSNumber numberWithInteger:2]];
	STAssertTrue([mul isEqualToNumber:[RSNumber numberWithInteger:20]], nil);
	
	//-(RSNumber *) multiplyWith:(RSNumber *) otherNumber mod:(RSNumber *)mod;
	mul = [number multiplyWith:[RSNumber numberWithInteger:2] mod:[RSNumber numberWithInteger:19]];
	STAssertTrue([mul isEqualToNumber:one], nil);
	
	//-(RSNumber *) divideWith:(RSNumber *) otherNumber
    RSNumber *blubb = [RSNumber numberWithInteger:8];
	RSNumber *div = [blubb divideWith:[RSNumber numberWithInteger:4]];
	STAssertTrue([div isEqualToNumber:[RSNumber numberWithInteger:2]], nil);
	
	//-(RSNumber *) toThePowerOf:(RSNumber *) otherNumber;
	RSNumber *pow = [number toThePowerOf:[RSNumber numberWithInteger:3]];
	STAssertTrue([pow isEqualToNumber:[RSNumber numberWithInteger:1000]], nil);
	
	//-(RSNumber *) toThePowerOf:(RSNumber *) otherNumber mod:(RSNumber *)mod;
	pow = [number toThePowerOf:[RSNumber numberWithInteger:3] mod:[RSNumber numberWithInteger:11]];
	STAssertTrue([pow isEqualToNumber:[RSNumber numberWithInteger:10]], nil);
}

@end
